package com.lyq.permission.service.impl;

import com.lyq.annotation.LYQPermission;
import com.lyq.permission.domain.Permission;
import com.lyq.permission.mapper.PermissionMapper;
import com.lyq.permission.service.IPermissionScanService;
import com.lyq.basic.utils.ClassUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @Author:liangyunqian
 * @Date: 2022/12/13  16:43
 * @Description:
 */
@Service
public class PermissionScanServiceImpl implements IPermissionScanService {

    @Value("${lyq.permission.scanPackage}")
    private String scanPackage;

    @Autowired
    private PermissionMapper permissionMapper;

    /**
     * 容器启动,权限扫描
     */
    @Override
    public void scan() {
        //1.扫描controller包下所有的Controller类
        List<Class> classes = ClassUtils.getAllClassName(this.scanPackage);

        List<Permission> permissions = new ArrayList<>();
        //2.循环所有的Controller
        for (Class aClass : classes) {
            //3.判断Controller类上是否有自定义注解
            LYQPermission classAnnotation = (LYQPermission)aClass.getAnnotation(LYQPermission.class);
            if(Objects.isNull(classAnnotation)){
                //如果没有自定义注解就说明当前这个类不需要权限就能访问,就直接跳过,不需要再去处理方法了
                continue;
            }
            Permission parent = new Permission();
            parent.setName(classAnnotation.name());
            parent.setDescs(classAnnotation.descs());
            //获取类名的url
            RequestMapping classRequestMapping = (RequestMapping)aClass.getAnnotation(RequestMapping.class);
            if (Objects.nonNull(classRequestMapping)) {
                parent.setUrl(classRequestMapping.value()[0]);
            }
            parent.setSn(aClass.getSimpleName());
            permissions.add(parent);
            //如果有自定义注解,就说明这个类里面的方法需要权限才能访问
            // 4.获取这个类里面所有的方法(反射)
            Method[] methods = aClass.getMethods();
            //5.判断方法上面有没有自定义注解
            for (Method method : methods) {
                LYQPermission methodAnnotation = method.getAnnotation(LYQPermission.class);
                if (Objects.isNull(methodAnnotation)) {
                    continue;//如果没有自定义注解,就说明该接口不需要权限来访问,就直接跳过不处理
                }
                //6.如果有注解,就封装Permission对象,并存到数据库的t_permission表中
                //一个@LYQPermission就有一个Permission对象
                Permission permission = new Permission();
                permission.setName(methodAnnotation.name());
                permission.setDescs(methodAnnotation.descs());
                //url  类上面的url + 方法上面的url
                permission.setUrl(getUrl(aClass, method));
                //sn  类名:方法名
                permission.setSn(aClass.getSimpleName()+":"+method.getName());
                permission.setParent(parent);
                permissions.add(permission);
            }
        }
        //将权限对象存到数据库
        //判断权限集合是否为空,如果不为空,就要操作数据库
        //删除所有权限
        permissionMapper.deleteAll();
        if(!CollectionUtils.isEmpty(permissions)){
            for (Permission permission : permissions) {
                permissionMapper.insert(permission);
            }
        }

    }
    private String getUrl(Class aClass,Method method){
        String url = "";
        //获取类名的url
        RequestMapping classRequestMapping = (RequestMapping)aClass.getAnnotation(RequestMapping.class);
        if (Objects.nonNull(classRequestMapping)) {
            url = classRequestMapping.value()[0];
        }
        //获取方法的url
        GetMapping getMapping = (GetMapping)method.getAnnotation(GetMapping.class);
        if (Objects.nonNull(getMapping) && getMapping.value().length>0) {
            url += getMapping.value()[0];
        }
        PostMapping postMapping = (PostMapping)method.getAnnotation(PostMapping.class);
        if (Objects.nonNull(postMapping)&& postMapping.value().length>0) {
            url += postMapping.value()[0];
        }
        PutMapping putMapping = (PutMapping)method.getAnnotation(PutMapping.class);
        if (Objects.nonNull(putMapping)&& putMapping.value().length>0) {
            url += putMapping.value()[0];
        }
        DeleteMapping deleteMapping = (DeleteMapping)method.getAnnotation(DeleteMapping.class);
        if (Objects.nonNull(deleteMapping)&& deleteMapping.value().length>0) {
            url += deleteMapping.value()[0];
        }
        PatchMapping PatchMapping = (PatchMapping)method.getAnnotation(PatchMapping.class);
        if (Objects.nonNull(PatchMapping)&& PatchMapping.value().length>0) {
            url += PatchMapping.value()[0];
        }
        return url;
    }
}
